package com.ala4.oxcafe.boot.utils;

import com.ala4.oxcafe.boot.dto.WeUserOpenDTO;
import com.ala4.oxcafe.boot.exception.WeChatException;
import com.ala4.oxcafe.common.utils.HttpUtil;
import com.ala4.oxcafe.common.utils.JSONUtil;
import com.ala4.oxcafe.common.utils.RedisUtil;
import com.ala4.oxcafe.common.utils.object.ObjectUtil;
import com.ala4.oxcafe.common.utils.text.StrUtil;
import com.ala4.oxcafe.constants.SecurityConstants;
import com.ala4.oxcafe.properties.WxAppProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 请求微信的接口
 *
 * @author PING
 * @date 2024/1/29 23:09
 */
@Slf4j
@Component
public class WxAppUtil {

    private static WxAppProperties wxAppProperties;

    public static String getWxAppAccessToken() {
        String accessToken = RedisUtil.get(SecurityConstants.WX_APP_ACCESS_TOKEN, String.class);
        if (StrUtil.isEmpty(accessToken)) {
            // 重新获取
            return getAccessToken();
        }
        return accessToken;
    }


    private static String getAccessToken() {
        String getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
                + wxAppProperties.getAppId() + "&secret=" + wxAppProperties.getAppSecret();

        String respStr = null;
        try {
            respStr = HttpUtil.get(getAccessTokenUrl);
        } catch (Exception exception) {
            log.error("请求微信AccessToken出现错误:", exception);
            throw new WeChatException(exception.getMessage());
        }

        Map<String, Object> respMap = JSONUtil.toMap(respStr);

        // 判断返回的参数是否有错误
        ifWxRespIsError(respMap, "获取微信AccessToken错误");

        String token = (String) respMap.get("access_token");

        RedisUtil.set(SecurityConstants.WX_APP_ACCESS_TOKEN, token, 7100);
        return token;
    }

    /**
     * 获取微信用户手机号
     *
     * @param phoneCode 小程序传递的phoneCode
     * @return
     */
    public static String getUserPhoneNumber(String phoneCode) {
        String wxAppAccessToken = getWxAppAccessToken();
        String getUserPhoneNumberUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + wxAppAccessToken;

        String respStr = null;
        try {
            respStr = HttpUtil.postJson(getUserPhoneNumberUrl, JSONUtil.toJsonStr(Map.of("code", phoneCode)));
        } catch (Exception exception) {
            log.error("请求微信用户信息(phoneNumber)出现错误:", exception);
            throw new WeChatException(exception.getMessage());
        }

        Map<String, Object> respMap = JSONUtil.toMap(respStr);

        ifWxRespIsError(respMap, "获取微信用户手机号错误");
        Map<String, String> phoneInfoMap = JSONUtil.toMapStr(respMap.get("phone_info"));

//        Map<String, Object> phoneInfoMap = JSONUtil.toMap((String) );

        return phoneInfoMap.get("purePhoneNumber");
    }

    private static void ifWxRespIsError(Map<String, Object> respMap, String errorMessage) {

        log.info("调用微信返回的参数:{}", JSONUtil.toJsonStr(respMap));
        Integer errCode = (Integer) respMap.get("errcode");
        if (ObjectUtil.isNotNull(errCode) && errCode != 0) {
            String errMsg = (String) respMap.get("errmsg");
            throw new WeChatException(errorMessage + errMsg);
        }
    }

    /**
     * 获取微信用户openId
     *
     * @param openCode
     */
    public static WeUserOpenDTO getUserOpenId(String openCode) {
        String getUserOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session?" +
                "appid=" + wxAppProperties.getAppId() +
                "&secret=" + wxAppProperties.getAppSecret() +
                "&js_code=" + openCode +
                "&grant_type=authorization_code";

        String respStr = null;
        try {
            respStr = HttpUtil.get(getUserOpenIdUrl);
        } catch (Exception exception) {
            log.error("请求微信用户信息(openId)出现错误:", exception);
            throw new WeChatException(exception.getMessage());
        }

        Map<String, Object> respMap = JSONUtil.toMap(respStr);

        ifWxRespIsError(respMap, "获取微信用户手机号错误");

        Object openId = respMap.get("openid");
        Object sessionKey = respMap.get("session_key");
        Object unionId = respMap.get("unionid");
        return new WeUserOpenDTO(openId, unionId, sessionKey);
    }

    @Autowired
    public void setWxProperties(WxAppProperties wxAppProperties) {
        WxAppUtil.wxAppProperties = wxAppProperties;
    }
}
